﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Backend.JYD.Model.Bid;
using Backend.JYD.Model;
using Backend.JYD.Model.Cust;

namespace Backend.JYD.BLL.Bid
{
    public class InviteInfoBLL
    {
        private static readonly IDAL.Bid.IInviteInfo idal = Factory.DALFactory.CreateEFDAL<IDAL.Bid.IInviteInfo>("DAL.InviteInfoDAL");

        public const int FLOW_DAY = 30; //单位：天。融资超过30天未满标，视为流标
        
        public enum enumInviteType { 竞标 = 0, 投标 = 1 }
        public enum enumInviteStatus { 无效 = -1, 初始 = 0, 发布投标中 = 1, 入围或标满 = 2, 流标 = 3, 定标或准备还款 = 4, 正常还款 = 5, 逾期 = 6, 正常垫资 = 7, 正常还完 = 8, 垫资结束 = 9 }
        
        public bool CheckBiddable(InviteInfo info)
        {
            if (info != null) return (info.Status == (int)enumInviteStatus.发布投标中);
            return false;
        }

        public bool CheckCancelBid(InviteInfo info)
        {
            //处于自由投标状态，或者刚满标还没有定标时，允许撤销
            if (info != null) return (info.Status == (int)enumInviteStatus.发布投标中 || (info.Type == (int)enumInviteType.投标 && info.Status == (int)enumInviteStatus.入围或标满));
            return false;
        }

        public decimal GetBiddableAmount(InviteInfo info)
        {
            if (CheckBiddable(info))
                if (info.Type == (int)enumInviteType.竞标)
                    return info.LoanMoney;
                else
                    return (info.LoanMoney - (info.BidAmount.HasValue ? (decimal)info.BidAmount : decimal.Zero));
            else
                return -1;
        }

        public Int64 AddInviteInfo(InviteInfo info)
        {
            if (string.IsNullOrWhiteSpace(info.CustNo)) return 0;
            if (info.IntentId <= 0) return 0;
            if (info.LoanMoney <= 0) return 0;
            if (info.Rate <= 0) return 0;
            if (info.Term <= 0) return 0;

            return idal.AddInviteInfo(info);
        }

        public bool UpdateInviteInfo(InviteInfo info)
        {
            if (string.IsNullOrWhiteSpace(info.CustNo)) return false;
            if (info.InviteId <= 0) return false;
            if (info.IntentId <= 0) return false;
            if (info.LoanMoney <= 0) return false;
            if (info.Rate <= 0) return false;
            if (info.Term <= 0) return false;

            BidRecordBLL bidBll = new BidRecordBLL();
            //已有投标者，则标的不能更新
            if (info.Status > (int)enumInviteStatus.发布投标中
                || (info.Status == (int)enumInviteStatus.发布投标中 && bidBll.GetdBidRecordsByInviteId(info.InviteId).Count > 0)) return false;
            
            return idal.UpdateInviteInfo(info);
        }

        public bool CancelInvite(InviteInfo info)
        {
            if (info == null || info.InviteId <= 0) return false;
            BidRecordBLL bidBll = new BidRecordBLL();
            //已有投标者，则标的不能取消
            if (info.Status > (int)enumInviteStatus.发布投标中
                || (info.Status == (int)enumInviteStatus.发布投标中 && bidBll.GetdBidRecordsByInviteId(info.InviteId).Count > 0)) return false;

            info.Status = (int)enumInviteStatus.无效;
            return idal.UpdateInviteInfo(info);
        }

        public bool UpdateInviteByAddBid(InviteInfo invite, BidRecord bid)
        {
            if (invite.Type == (int)InviteInfoBLL.enumInviteType.投标)
            {
                invite.BidAmount += bid.LoanMoney;
                if (invite.BidAmount >= invite.LoanMoney) invite.Status = (int)InviteInfoBLL.enumInviteStatus.入围或标满;
            }
            return idal.UpdateInviteInfo(invite);
        }

        public bool UpdateInviteByUpdateBid(InviteInfo invite, BidRecord oldBid, BidRecord newBid)
        {
            if (invite.Type == (int)InviteInfoBLL.enumInviteType.投标 && invite.BidAmount - oldBid.LoanMoney + newBid.LoanMoney <= invite.LoanMoney)
            {
                invite.BidAmount = invite.BidAmount - oldBid.LoanMoney + newBid.LoanMoney;
                if (invite.Type == (int)InviteInfoBLL.enumInviteType.投标 && invite.BidAmount == invite.LoanMoney)
                    invite.Status = (int)InviteInfoBLL.enumInviteStatus.入围或标满;
                else
                    invite.Status = (int)InviteInfoBLL.enumInviteStatus.发布投标中;
                return idal.UpdateInviteInfo(invite);
            }
            return false;
        }

        public bool UpdateInviteByCancelBid(InviteInfo invite, BidRecord bid)
        {
            if (invite.Type == (int)InviteInfoBLL.enumInviteType.投标)
            {
                invite.BidAmount -= bid.LoanMoney;
                invite.Status = (int)InviteInfoBLL.enumInviteStatus.发布投标中;
                return idal.UpdateInviteInfo(invite);
            }
            return false;
        }

        public InviteInfo GetdInviteInfoByInviteId(Int64 inviteId)
        {
            if (inviteId <= 0) return null;
            return idal.GetInviteInfoByInviteId(inviteId);
        }

        public IList<InviteInfo> GetdInviteInfoByCustNo(string custNo)
        {
            if (string.IsNullOrWhiteSpace(custNo)) return null;
            return idal.GetInviteInfoByCustNo(custNo);
        }

        public PageInfo<InviteInfo> GetRunInviteInfoByPage(PageInfo page)
        {
            int[] status = new int[] { (int)enumInviteStatus.发布投标中,
                                        (int)enumInviteStatus.定标或准备还款,
                                        (int)enumInviteStatus.入围或标满,
                                        (int)enumInviteStatus.正常还款 };
            return idal.GetRunInviteInfoByPage(page, status);
        }

        public IList<InviteInfo> GetAutoInviteList(DateTime startDate, int interval)
        {
            if (startDate == null) startDate = DateTime.Now.AddMinutes(-interval);
            return idal.GetAutoInviteInfo((int)enumInviteStatus.发布投标中, startDate);
        }

        public IList<InviteInfo> GetFlowInviteList(DateTime endDate)
        {
            if (endDate == null) endDate = DateTime.Today;
            return idal.GetFlowInviteInfo((int)enumInviteStatus.发布投标中, endDate);
        }
        
        //审核融资需求
        public bool VerifyInvite(InviteInfo invite)
        {
            if (invite.Status == (int)enumInviteStatus.初始)
            {
                invite.Status = (int)enumInviteStatus.发布投标中;
                invite.BidStartDate = DateTime.Now;
                invite.BidEndDate = DateTime.Now.AddDays(FLOW_DAY);

                return idal.UpdateInviteInfo(invite);
            }
            return false;
        }

        //流标
        public int FlowInvite(DateTime start)
        {
            int flowNum = 0;
            IList<InviteInfo> lstInvite = GetFlowInviteList(start);
            if (lstInvite != null)
            {
                BidRecordBLL bidBll = new BidRecordBLL();
                foreach (InviteInfo invite in lstInvite)
                {
                    //流标
                    bidBll.FlowBid(invite);
                    
                    invite.Status = (int)enumInviteStatus.流标;
                    invite.BidAmount = 0;
                    idal.UpdateInviteInfo(invite);

                    flowNum++;
                }
            }
            return flowNum;
        }

        //定标或还款中 = 4
        public bool ExecInvite(InviteInfo info, UserAccount acc)
        {
            if (info != null && info.InviteId > 0 && info.Status == (int)enumInviteStatus.入围或标满)
            {
                PayPlanBLL planBll = new PayPlanBLL();
                BidRecordBLL bidBll = new BidRecordBLL();

                if (info.PlanType == (int)PayPlanBLL.enumPlanType.等额本息)
                {
                    decimal monthlyRate = info.Rate / 12 / 100;
                    decimal monthlyAmount = PayPlanBLL.MonthlyAverageCapital(info.LoanMoney, monthlyRate, info.Term);
                    
                    //创建还款计划
                    planBll.CreatePayPlan(info, monthlyAmount);
                    //更新所有投标记录
                    bidBll.ExecBid(info, monthlyAmount);
                }
                info.PlanType = (int)PayPlanBLL.enumPlanType.等额本息;
                info.AccId = acc.AccId;
                info.Status = (int)enumInviteStatus.定标或准备还款;
                return idal.UpdateInviteInfo(info);
            }
            return false;
        }

        //返回true表示正常还款，false表示逾期
        public bool PayInvite(PayPlan plan)
        {
            BidRecordBLL bidBll = new BidRecordBLL();
            InviteInfo invite = idal.GetInviteInfoByInviteId(plan.InviteId);
            var lstBidRec = bidBll.GetdBidRecordsByInviteId(plan.InviteId);

            //尽量不允许出现部分还款，部分逾期的情况。
            //通过第三方支付，判断余额是否充足...

            bool planRet = true;
            foreach (BidRecord bid in lstBidRec)
            {
                bool payRet = true;
                bool isLast = plan.IsLastPlan.HasValue && plan.IsLastPlan.Value;

                //按bidrecord记录，通过第三方转账支付...

                //更新投标信息
                bidBll.PayBid(bid, payRet, isLast);
                
                if (payRet)
                {
                    if (isLast)
                    {
                        invite.Status = (int)enumInviteStatus.正常还完;
                        idal.UpdateInviteInfo(invite);
                    }
                    else if (invite.Status != (int)InviteInfoBLL.enumInviteStatus.正常还款)
                    {
                        invite.Status = (int)InviteInfoBLL.enumInviteStatus.正常还款;
                        idal.UpdateInviteInfo(invite);
                    }
                }
                else
                {
                    planRet = false;

                    if (invite.Status != (int)InviteInfoBLL.enumInviteStatus.逾期)
                    {
                        invite.Status = (int)InviteInfoBLL.enumInviteStatus.逾期;
                        idal.UpdateInviteInfo(invite);
                    }
                }
            }
            return planRet;
        }

        public bool RepayInvite(long inviteId, int repayTerm, PayPlanBLL.enumRepayType repayType)
        {
            InviteInfo invite = idal.GetInviteInfoByInviteId(inviteId);
            if (repayType == PayPlanBLL.enumRepayType.逾期了结 ||
                    repayTerm == invite.Term)
                invite.Status = (int)InviteInfoBLL.enumInviteStatus.垫资结束;
            else
                invite.Status = (int)InviteInfoBLL.enumInviteStatus.正常垫资;
            return idal.UpdateInviteInfo(invite);
        }

    }
}
